Using NodesUsing Video NodeOn this pageUsing Video Node The VideoNode is a node class in Dora SSR that allows you to play video files in your game scenes. It inherits from Sprite, which means you can use all the properties and methods available to sprite nodes, such as positioning, scaling, rotation, and more. Once a VideoNode is mounted to the game scene, it will automatically start playing the video and continue playing until the node is removed from the scene. This tutorial will guide you through using VideoNode, including how to prepare video files in the correct format and how to use VideoNode in your game. 1. Video Format Requirements VideoNode accepts an Ogg container with a Theora video stream. Files are read through Dora Content, so packaged resources and mounted archives use the same path rules as other assets. 1.1 Supported Video Format Container: Ogg (.ogv) Video codec: Theora Color format: Theora 4:2:0, 4:2:2, and 4:4:4 streams are accepted and converted to RGBA for rendering Audio: VideoNode renders video only. Love Video may separately synchronize an audio Source through Dora SoLoud. Resolution/performance: 4K and high-bitrate streams may be CPU intensive for software decoding For smooth playback on mid-range devices, 720p/1080p and moderate bitrates are recommended 1.2 Converting Videos Using FFmpeg Use an FFmpeg build with the libtheora encoder to create an Ogg/Theora file: Converting MP4 to Ogg/Theora # Basic conversionffmpeg -i input.mp4 -c:v libtheora -q:v 7 -pix_fmt yuv420p -an output.ogv# With specific resolution and bitrate (recommended for better performance)ffmpeg -i input.mp4 -c:v libtheora -q:v 7 -pix_fmt yuv420p -s 1280x720 -r 30 -an output.ogv# For 1080p videoffmpeg -i input.mp4 -c:v libtheora -q:v 7 -pix_fmt yuv420p -s 1920x1080 -r 30 -an output.ogv Parameter explanations: -c:v libtheora: Use the Theora encoder -q:v 7: Select video quality (adjust for size and quality) -pix_fmt yuv420p: Set pixel format to YUV 4:2:0 -s 1280x720: Set resolution (optional, adjust as needed) -r 30: Set frame rate to 30 fps (optional, adjust as needed) -an: Remove audio track Converting Other Formats # Convert from AVIffmpeg -i input.avi -c:v libtheora -q:v 7 -pix_fmt yuv420p -an output.ogv# Convert from MOVffmpeg -i input.mov -c:v libtheora -q:v 7 -pix_fmt yuv420p -an output.ogv TipAfter conversion, keep the .ogv extension and place the file in the project's Content resource tree. 2. Creating a VideoNode Instance To create a VideoNode, you need to provide the path to the video file. The VideoNode constructor accepts two parameters: filename: The Content path to an Ogg/Theora video file (normally .ogv) looped: (Optional) Whether the video should loop. Default is false LuaTealTypeScriptYueScriptlocal VideoNode <const> = require("VideoNode")-- Create a VideoNode that plays oncelocal video = VideoNode("assets/video.ogv")-- Create a VideoNode that loopslocal loopingVideo = VideoNode("assets/video.ogv", true)local VideoNode <const> = require("VideoNode")-- Create a VideoNode that plays oncelocal video = VideoNode("assets/video.ogv")-- Create a VideoNode that loopslocal loopingVideo = VideoNode("assets/video.ogv", true)import { VideoNode } from "Dora";// Create a VideoNode that plays onceconst video = VideoNode("assets/video.ogv");// Create a VideoNode that loopsconst loopingVideo = VideoNode("assets/video.ogv", true);_ENV = Dora-- Create a VideoNode that plays oncevideo = VideoNode "assets/video.ogv"-- Create a VideoNode that loopsloopingVideo = VideoNode "assets/video.ogv", true ImportantIf the video file cannot be loaded or the format is incorrect, VideoNode() will return nil (or null in TypeScript). Always check if the node was created successfully before using it. 3. Mounting VideoNode to the Scene Once you create a VideoNode instance, you need to mount it to the game scene for it to be displayed and start playing. When a VideoNode is mounted to the scene, it will automatically begin playing the video and continue playing until the node is removed from the scene. LuaTealTypeScriptYueScriptlocal VideoNode <const> = require("VideoNode")local Vec2 <const> = require("Vec2")-- Create a VideoNodelocal video = VideoNode("assets/video.ogv")if video then -- Set position video.position = Vec2(400, 300) -- Mount to the scene (video will start playing automatically) -- The video will continue playing as long as the node is in the sceneendlocal VideoNode <const> = require("VideoNode")local Vec2 <const> = require("Vec2")-- Create a VideoNodelocal video = VideoNode("assets/video.ogv")if not video is nil then -- Set position video.position = Vec2(400, 300) -- Mount to the scene (video will start playing automatically) -- The video will continue playing as long as the node is in the sceneendimport { VideoNode, Vec2 } from "Dora";// Create a VideoNodeconst video = VideoNode("assets/video.ogv");if (video) { // Set position video.position = Vec2(400, 300); // Mount to the scene (video will start playing automatically) // The video will continue playing as long as the node is in the scene}_ENV = Dora-- Create a VideoNodewith VideoNode "assets/video.ogv" -- Set position .position = Vec2 400, 300 -- Mount to the scene (video will start playing automatically) -- The video will continue playing as long as the node is in the scene Automatic PlaybackOnce a VideoNode is mounted to the game scene, it will automatically start playing the video. The video will continue playing frame by frame as long as the node remains in the scene tree. If you set looped to true, the video will automatically restart from the beginning when it reaches the end. 4. Controlling Video Playback Since VideoNode inherits from Sprite, you can use all sprite properties and methods to control the video display: LuaTealTypeScriptYueScriptlocal VideoNode <const> = require("VideoNode")local Vec2 <const> = require("Vec2")local Scale <const> = require("Scale")local video = VideoNode("assets/video.ogv", true) -- Loop enabledif video then -- Position the video video.position = Vec2(400, 300) -- Scale the video video.scaleX = 0.5 video.scaleY = 0.5 -- Rotate the video video.angle = 45 -- Set opacity video.opacity = 0.8 -- Or use action to animate video:perform(Scale(2.0, 0.5, 1.0)) -- Scale from 0.5 to 2.0 over 1 secondendlocal VideoNode <const> = require("VideoNode")local Vec2 <const> = require("Vec2")local Scale <const> = require("Scale")local video = VideoNode("assets/video.ogv", true) -- Loop enabledif not video is nil then -- Position the video video.position = Vec2(400, 300) -- Scale the video video.scaleX = 0.5 video.scaleY = 0.5 -- Rotate the video video.angle = 45 -- Set opacity video.opacity = 0.8 -- Or use action to animate video:perform(Scale(2.0, 0.5, 1.0)) -- Scale from 0.5 to 2.0 over 1 secondendimport { VideoNode, Vec2, Scale } from "Dora";const video = VideoNode("assets/video.ogv", true); // Loop enabledif (video) { // Position the video video.position = Vec2(400, 300); // Scale the video video.scaleX = 0.5; video.scaleY = 0.5; // Rotate the video video.angle = 45; // Set opacity video.opacity = 0.8; // Or use action to animate video.perform(Scale(2.0, 0.5, 1.0)); // Scale from 0.5 to 2.0 over 1 second}_ENV = Dorawith VideoNode "assets/video.ogv", true -- Loop enabled -- Position the video .position = Vec2 400, 300 -- Scale the video .scaleX = 0.5 .scaleY = 0.5 -- Rotate the video .angle = 45 -- Set opacity .opacity = 0.8 -- Or use action to animate \perform Scale 2.0, 0.5, 1.0 -- Scale from 0.5 to 2.0 over 1 second 5. Removing VideoNode from Scene To stop the video playback, simply remove the VideoNode from the scene: LuaTealTypeScriptYueScript-- Remove the video node from its parent (stops playback)video:removeFromParent()-- Remove the video node from its parent (stops playback)video:removeFromParent()// Remove the video node from its parent (stops playback)video.removeFromParent();-- Remove the video node from its parent (stops playback)video\removeFromParent() 6. Complete Example Here's a complete example that demonstrates creating a VideoNode, positioning it, and handling it in a game scene: LuaTealTypeScriptYueScriptlocal VideoNode <const> = require("VideoNode")local Vec2 <const> = require("Vec2")local Size <const> = require("Size")-- Create a looping video nodelocal video = VideoNode("assets/background_video.ogv", true)if video then -- Scale to fit screen if needed local visualSize = App.visualSize local videoSize = video.size local scaleX = visualSize.width / videoSize.width local scaleY = visualSize.height / videoSize.height local scale = math.min(scaleX, scaleY) video.scaleX = scale video.scaleY = scale -- Video will start playing automatically when mounted to scene -- It will continue playing and loop as long as the node is in the sceneendlocal VideoNode <const> = require("VideoNode")local Vec2 <const> = require("Vec2")local Size <const> = require("Size")-- Create a looping video nodelocal video = VideoNode("assets/background_video.ogv", true)if not video is nil then -- Scale to fit screen if needed local visualSize = App.visualSize local videoSize = video.size local scaleX = visualSize.width / videoSize.width local scaleY = visualSize.height / videoSize.height local scale = math.min(scaleX, scaleY) video.scaleX = scale video.scaleY = scale -- Video will start playing automatically when mounted to scene -- It will continue playing and loop as long as the node is in the sceneendimport { VideoNode, Vec2, Size, App } from "Dora";// Create a looping video nodeconst video = VideoNode("assets/background_video.ogv", true);if (video) { // Scale to fit screen if needed const visualSize = App.visualSize; const videoSize = video.size; const scaleX = visualSize.width / videoSize.width; const scaleY = visualSize.height / videoSize.height; const scale = Math.min(scaleX, scaleY); video.scaleX = scale; video.scaleY = scale; // Video will start playing automatically when mounted to scene // It will continue playing and loop as long as the node is in the scene}_ENV = Dora-- Create a looping video nodewith VideoNode "assets/background_video.ogv", true -- Scale to fit screen if needed visualSize = App.visualSize videoSize = .size scaleX = visualSize.width / videoSize.width scaleY = visualSize.height / videoSize.height scale = math.min scaleX, scaleY .scaleX = scale .scaleY = scale -- Video will start playing automatically when mounted to scene -- It will continue playing and loop as long as the node is in the scene 7. Performance Considerations When using VideoNode, keep the following performance tips in mind: Resolution: Use appropriate resolutions (720p or 1080p) for your target devices. Higher resolutions require more CPU power for decoding. Bitrate: Moderate bitrates provide a good balance between quality and performance. Very high bitrates can cause stuttering on lower-end devices. Frame Rate: Constant frame rates (CFR) are recommended. Variable frame rates may cause timing issues. Multiple Videos: Playing multiple videos simultaneously can be CPU intensive. Consider limiting the number of concurrent VideoNodes. Background Processing: VideoNode uses a background thread for decoding, which helps maintain smooth gameplay, but still requires CPU resources. 8. Conclusion In this tutorial, you learned how to: Prepare video files in the correct Ogg/Theora format using FFmpeg Create VideoNode instances Mount VideoNodes to the game scene (which automatically starts playback) Control video display using Sprite properties Handle video looping Remember that VideoNode will automatically start playing when mounted to the scene and continue playing as long as it remains in the scene tree. This makes it perfect for background videos, cutscenes, or any scenario where you need continuous video playback in your game. For more information about VideoNode, refer to the VideoNode API documentation.